//
// gcs.h
// gcs
// Grand Central Station, controlling process of the Protea Server / contains global definitions and main entry point
// Copyright (C) 2003, 2004, 2005 eXegeSys, Inc.
// Copyright (C) 2008 Bruce A. James
//
// This program is part of the Protea Project.
//
// The Protea Project is free software; you can redistribute it and/or modify it 
// under the terms of the GNU General Public License as published by the 
// Free Software Foundation, either version 3 of the License, or (at your 
// option) any later version.
//
// The Protea Project is distributed in the hope that it will be useful, but 
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 
// for more details.
// 
// You should have received a copy of the GNU General Public License along 
// with this program.  If not, see <http://www.gnu.org/licenses/>.
// 
// Please send correspondence to:
// 
// theproteaproject@gmail.com
//

/*	\file gcs.h
	\brief Grand Central Station - Central server control

	Grand Central Station - The central process of the Traffic processing system.
	All interface connections initially connect to GCS before being redirected.	

	Usage : gcs <listen_port> [\<alt_start\>]
		
		listen_port - Listener socket port for accepting connections
		alt_start (optional) - Alternate bootstrap process, uses gcsboot if not
			specifed.
*/

#ifndef __PROTEA_GCS_H__
#define __PROTEA_GCS_H__

#include "../OSDep/service.h"
#include "gcs_session.h"

#include "../Utils/defns1.h"
using namespace ProteaApp1;

#define ADMIN_LOG_FILENAME "admin.log"


enum verify_type {
	VERIFY_ADD = 0,
	VERIFY_CHANGE = 1,
	VERIFY_DELETE = 2,
	VERIFY_REVIEW = 3,
	VERIFY_COPY = 4
};


// Forward declaration
class XCSubstation;


// Maintains process statistics, such as number of messages sent/recv'd
class XCProcessStats : public XCBase
{
public:
	XCProcessStats();
	virtual ~XCProcessStats();

	long	pid;			// Process ID
	long	listenport;		// Listener Port for Process
	long	parentpid;		// Process ID of Parent Process

	long	trans_complete;
	long	trans_open;
	long	trans_stated;

	long	msg_sent;
	long	msg_recv;

	double	last_check;
	double	cpu_time;
	double	start_time;

	int		debug_type_filter;
	int		debug_level_cutoff[ num_tc ];

	char*	filename;
	char*	host;
};


// Maintains information for an application
class XCApplication : public XCProcessStats 
{
public:
	long LoadBalanceScore();

	long number;
	XCSubstation* owner;

	XCApplication* next_in_app_list;
	XCApplication* next_in_sub_list;
};



class XCApplicationList {
public:
	int number;
	XCApplication* first_app;
	XCApplicationList* next;
};



class XCInterface : public XCProcessStats
{
public:
	XCInterface( startup_message* start_msg, XCMsgPortPtr port );
	~XCInterface();

	XCMsgPortPtr msg_port;
	XCInterface* next;
};



class XCSubstation : public XCProcessStats
{
public:
	XCSubstation( const char* name, XCMsgPortPtr port );
	~XCSubstation();

	XCSubstation* next;
	XCMsgPortPtr msg_port;
	XCApplication* applist;

	const char* GetHostName() const { return hostname; };

	XCApplication* AddApplication( startup_message* start_msg );
	void RemoveApplication( XCApplication* app );
	XCApplication* FindApplication( int pid );

	XCProcessStats* FindPID( long pid );
	XCProcessStats* FindStatusPID( status_message* statmsg );

private:
	char* hostname;
};





class XCGCSTransaction : public XCBase
{
public:
	long id;
	XCApplication* host;
	XCGCSTransaction* next;
};



class XCGCSTransactionList : public XCBase
{
public:
	XCGCSTransactionList();

	XCGCSTransaction* Find( long id );
	XCGCSTransaction* Add( long id );
	void Remove( long id );
	void RemoveApp( XCApplication* app );

	XCGCSTransaction* transactions;
};




class XCSubstationList : public XCBase 
{
public:
	XCSubstationList();
	~XCSubstationList();

	XCSubstation* AddHost( startup_message* startmsg, XCMsgPortPtr port );
	XCSubstation* FindHost( const char* hostname );
	XCSubstation* FindHost( XCMsgPortPtr port );
	void RemoveHost( XCSubstation* );

	void AddApplication( startup_message* start_msg, XCMsgPortPtr port );
	void RemoveApplication( XCApplication* );
	void RemoveApplication( XCMsgPort* host, int pid );

	void AddInterface( startup_message* start_msg, XCMsgPortPtr port );
	void RemoveInterface( XCInterface* );

	void Shutdown();

	XCApplication* LoadBalance( int appnum );

	XCCriticalSection crit;

	XCSubstation* GetFirstHost() { return hosts; };
	XCInterface* GetFirstInterface() { return interfaces; };
	XCApplicationList* GetAppList() { return applist; };
	XCGCSTransactionList* GetTransList() { return &translist; };

protected:
	XCSubstation* hosts;
	XCInterface* interfaces;
	XCApplicationList* applist;
	XCGCSTransactionList translist;
};




// XCGCS Class - Grand Central Station
class XCGCS : public XCAppInterface, public XCService, public XCProcessStats, public parms_reader
{
public:
	// Constructor
	XCGCS( char* name, char* dispname, char* desc, void* func, char* deps );

	// Destructor
	~XCGCS();
	/*
		\brief Received Message processing function
		\param msg [in] Message received
		\param inport [in] Port number message was received from

		This function is called when a message is received from any of the ports 
		(socket listener, connected sockets or pipes) registered for this object.
	*/
	bool GotMessage( XCMsgPort* port, XCToolsMessage* msg );
	XCTransactionInfo* OnTransaction( XCTransactionInfo* transaction );
	void OnDroppedConnection( XCMsgPortPtr tempport );

	XCSubstationList hostlist;			// list of available substation hosts
	void StartUp();

	//
	// All GCS/SAI Transactions
	//

	TRANSACTION( RevAllProcess );		// Review all processes
	TRANSACTION( ProcessDetail );		// Return detail process information
	TRANSACTION( SetTraceLevel );		// Set Debug Trace Level for a remote process

	TRANSACTION( SetListenerPort );		// Set GCS Listener Port Number
	TRANSACTION( UpdateApplication );	// Update Application Configuration
	TRANSACTION( UpdateInterface );		// Update Interface Configuration

	TRANSACTION( ReviewLicenses );		// Review active license usage

	TRANSACTION( PrepApplication );		// Prep an application

	TRANSACTION( AddUser );
	TRANSACTION( ChangeUser );
	TRANSACTION( RemoveUser );
	TRANSACTION( ListUsers );
	TRANSACTION( ReviewUser );

	TRANSACTION( AddGroup );
	TRANSACTION( RemoveGroup );
	TRANSACTION( ListGroups );
	TRANSACTION( ReviewGroup );

	TRANSACTION( AddUserToGroup );
	TRANSACTION( RemoveUserFromGroup );

	TRANSACTION( ListApplications );
	TRANSACTION( ReviewApplication );

	TRANSACTION( AddAppSecurity );
	TRANSACTION( DelAppSecurity );
	TRANSACTION( ChgAppSecurity );

	TRANSACTION( AddAppSecurityUser );
	TRANSACTION( DelAppSecurityUser );
	TRANSACTION( ChgAppSecurityUser );

	TRANSACTION( ReviewApplicationSubItem );

	TRANSACTION( ReviewAdminLogs );
	TRANSACTION( ReviewGeneralStats );

	TRANSACTION( Shutdown );


	//
	// JOB SCHEDULING FUNCTIONALITY
	//
	TRANSACTION( AddJob );
	TRANSACTION( DeleteJob );
	TRANSACTION( ChangeJob );
	TRANSACTION( ReviewJobSchedule );
	TRANSACTION( ReviewJobHistory );

	XCDBStatement* OrderJobs( XCBuffer* job_schedule, bool active_only, XCTransactionVars* vars );
	void ExecuteJobs();
	void ExecuteComplete( XCBuffer* job_schedule, bool success, const char* message, XCBuffer* original = NULL, XCTxn* txn = NULL );
	void HandleTransactionResponse( XCTransactionInfo* txn );

	// Database helper transactions
	void DatabaseAdd( XCBuffer* buffer, XCTransactionVars* vars );
	void DatabaseRemove( XCBuffer* buffer, XCTransactionVars* vars );
	void DatabaseChange( XCBuffer* original_buffer, XCBuffer* new_buffer, XCTransactionVars* vars );
	bool DatabaseRetrieve( XCBuffer* buffer, XCTransactionVars* vars );

	bool LogAdminMsg( admin_message* admin );

	bool shutdown;

protected:	
	static THREAD_PROCEDURE ExecuteSingleJob( void* parm );
	static THREAD_PROCEDURE SchedulerThread( void* parm );

	GCSSessionsList licensing;

	bool HandleStatusMsg( status_message* statmsg, XCMsgPortPtr port );
	bool HandleDispatchMessage( XCMsgPort* port, XCToolsMessage* msg );
	bool HandleTransactionMessage( XCMsgPort* port, XCToolsMessage* msg );
	void GCSMessage( int msg_nbr );

	void GetProcessInfo( XCBuffer* detail, XCProcessStats* temp, double currenttime );

	bool AllowUI;		// flag for allowing a UI to connect to me...
	XCMsgPortPtr murderer;	// the process that will eventually kill me...
	fstream admin_log;	// file for reading/writing admin messages

	// All GCS/SAI SubTransactions
	//

	// Save the configuration file with current settings
	void SaveConfig();

	// Set the listener port number
	void SetPort( const char* port );

	// Daemon functions
	void OnInit();
	void OnRun();
	void OnSignalStop();
	void OnCleanup();
	void StartInterfaces();

	XCTiming timer;
};

#endif
